﻿using Sage.WindowsProcess.Models;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;

namespace Sage.WindowsProcess.Parent
{
    /// <summary>
    /// 提供获取父进程信息的工具类
    /// </summary>
    [SupportedOSPlatform("windows")]
    public static partial class ParentProcessUtility
    {
        // Win32 API 结构定义
        [StructLayout(LayoutKind.Sequential)]
        private struct PROCESS_BASIC_INFORMATION
        {
            public IntPtr Reserved1;
            public IntPtr PebBaseAddress;
            public IntPtr Reserved2_0;
            public IntPtr Reserved2_1;
            public IntPtr UniqueProcessId;
            public IntPtr InheritedFromUniqueProcessId; // 父进程ID存储在这里
        }

        // 使用 LibraryImport 特性代替 DllImport
        // 这允许编译器在编译时生成 P/Invoke 封送代码，提高性能
        [LibraryImport("kernel32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static partial bool CloseHandle(IntPtr hObject);

        [LibraryImport("kernel32.dll")]
        private static partial IntPtr GetCurrentProcess();

        [LibraryImport("ntdll.dll", SetLastError = true)]
        private static partial int NtQueryInformationProcess(
            IntPtr processHandle,
            int processInformationClass, // 0 = ProcessBasicInformation
            ref PROCESS_BASIC_INFORMATION processInformation,
            int processInformationLength,
            out int returnLength);

        /// <summary>
        /// 获取当前进程的父进程ID
        /// </summary>
        /// <returns>父进程ID，如果获取失败则返回-1</returns>
        public static int GetParentProcessId()
        {
            // 获取当前进程句柄
            var hProcess = GetCurrentProcess();

            // 初始化进程基本信息结构 - 使用简化的 new 表达式
            var pbi = new PROCESS_BASIC_INFORMATION();

            try
            {
                // 调用 NtQueryInformationProcess 获取进程信息
                int status = NtQueryInformationProcess(
                    hProcess,
                    0, // ProcessBasicInformation
                    ref pbi,
                    Marshal.SizeOf<PROCESS_BASIC_INFORMATION>(), // 使用泛型版本提高 AOT 兼容性
                    out _); // 使用弃元 _ 忽略不需要的输出参数

                // 检查 API 调用是否成功
                if (status != 0)
                    return -1;

                // 返回父进程ID
                return pbi.InheritedFromUniqueProcessId.ToInt32();
            }
            finally
            {
                // 确保进程句柄被正确关闭，防止资源泄漏
                CloseHandle(hProcess);
            }
        }

        /// <summary>
        /// 获取父进程完整路径
        /// </summary>
        /// <returns>父进程路径，如果获取失败则返回错误信息</returns>
        public static string GetParentProcessPath()
        {
            // 先获取父进程ID
            int parentPid = GetParentProcessId();
            if (parentPid <= 0)
                return "无法获取父进程ID";

            try
            {
                // 通过进程ID获取进程对象
                using var parentProcess = Process.GetProcessById(parentPid);

                // 尝试获取主模块的文件名（即进程的可执行文件路径）
                // 注意：这可能需要管理员权限
                return parentProcess.MainModule?.FileName ?? "无法获取父进程路径";
            }
            catch (ArgumentException ex)
            {
                // 进程ID无效
                return $"进程ID无效: {ex.Message}";
            }
            catch (InvalidOperationException ex)
            {
                // 进程可能已退出
                return $"无法访问进程: {ex.Message}";
            }
            catch (System.ComponentModel.Win32Exception ex)
            {
                // 权限不足，通常需要管理员权限
                return $"访问被拒绝: {ex.Message}";
            }
        }

        /// <summary>
        /// 获取父进程名称
        /// </summary>
        /// <returns>父进程名称，如果获取失败则返回错误信息</returns>
        public static string GetParentProcessName()
        {
            // 先获取父进程ID
            int parentPid = GetParentProcessId();
            if (parentPid <= 0)
                return "无法获取父进程ID";

            try
            {
                // 通过进程ID获取进程对象 - 使用简化的 using 声明
                using var parentProcess = Process.GetProcessById(parentPid);

                // 返回进程名称（不包含路径和扩展名）
                return parentProcess.ProcessName;
            }
            catch (ArgumentException ex)
            {
                return $"进程ID无效: {ex.Message}";
            }
            catch (InvalidOperationException ex)
            {
                return $"无法访问进程: {ex.Message}";
            }
            catch (System.ComponentModel.Win32Exception ex)
            {
                return $"访问被拒绝: {ex.Message}";
            }
        }

        /// <summary>
        /// 获取父进程的完整信息
        /// </summary>
        /// <returns>包含父进程ID、名称和路径的实体类</returns>
        public static ParentProcessInfo GetParentProcessInfo()
        {
            int id = GetParentProcessId();
            return new ParentProcessInfo(
                id,
                id > 0 ? GetParentProcessName() : "未知",
                id > 0 ? GetParentProcessPath() : "未知"
            );
        }
    }
}
